/**
 * Copyright (c) 2016-2020 https://github.com/zhaohuatai
 *
 * contact z_huatai@qq.com
 *  
 */
package org.zfes.snowy.auth.biz.service.impl;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zfes.snowy.auth.biz.dao.AuthUserRoleMapper;
import org.zfes.snowy.auth.biz.model.AuthUserRole;
import org.zfes.snowy.auth.biz.service.IAuthUserRoleService;
import org.zfes.snowy.auth.shiro.event.AuthCacheClearType;
import org.zfes.snowy.auth.shiro.event.AuthChangeEvent;
import org.zfes.snowy.base.dao.params.ParamMap;
import org.zfes.snowy.core.data.DataSet;
import org.zfes.snowy.core.idcenter.IDGenerator;
import org.zfes.snowy.core.util.ZAlert;
import org.zfes.snowy.core.util.ZStrUtil;
@Service
@Lazy(true)
public class AuthUserRoleServiceImpl implements IAuthUserRoleService{
	@Autowired
	private AuthUserRoleMapper authUserRoleMapper;
	@Autowired
	private  ApplicationEventPublisher publisher;
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public List<String> loadRoleCodesInUserRoleByUserId(Long userId,String appkey,Boolean enabled) {
		if(userId==null||ZStrUtil.hasNoText(appkey)){
			return Collections.emptyList();
		}
		return authUserRoleMapper.selectRoleCodesByUserId(userId,appkey,enabled);
	}
	
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public List<Long> loadRoleIdsInUserRoleByUserId(Long userId,String appkey,Boolean enabled){
		if(userId==null||ZStrUtil.hasNoText(appkey)){
			return Collections.emptyList();
		}
		return authUserRoleMapper.selectRoleIdsByUserId(userId, appkey, enabled);
	 }
	
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public List<Long> loadUserIdsInUserRoleByRoleId(Long roleId,String appkey,Boolean enabled){
		if(roleId==null||ZStrUtil.hasNoText(appkey)){
			return Collections.emptyList();
		}
		return authUserRoleMapper.selectUserIdsByRoleId(roleId, appkey, enabled);
		
	}
	@Transactional(rollbackFor=Exception.class,readOnly=true)
	@Override
	public List<Long> loadUserIdsInUserRoleByRoleCode(String roleCode,String appkey,Boolean enabled){
		if(ZStrUtil.hasNoText(roleCode)||ZStrUtil.hasNoText(appkey)){
			return Collections.emptyList();
		}
		return authUserRoleMapper.selectUserIdsByRoleCode(roleCode, appkey, enabled);
	}
	@Transactional(rollbackFor=Exception.class)
	@Override
	public  void addRolesToUserRole(List<Long> roleIds,Long userId){
		if(userId==null||roleIds==null||roleIds.isEmpty()){
			ZAlert.Error("请选择数据");
		}
		roleIds=roleIds.stream().distinct().collect(Collectors.toList());
			
		removeRolesFromUserRole(roleIds,userId);
		
		List<AuthUserRole> userRoleList=roleIds.stream().map(val->new AuthUserRole(IDGenerator.genLongId(), val,  userId)).collect(Collectors.toList());
		
		authUserRoleMapper.batchInsertUserRole(userRoleList);
		
		this.publisher.publishEvent(new AuthChangeEvent(SecurityUtils.getSubject(),AuthCacheClearType.cachedAuthorizationInfoBySubject));
	}
	
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void addUsersToUserRole(List<Long> userIds,Long roleId){
		if(roleId==null||userIds==null||userIds.isEmpty()){
			ZAlert.Error("请选择数据");
		}
		userIds=userIds.stream().distinct().collect(Collectors.toList());
		
		removeUsersFromUserRole( userIds, roleId);
		
		List<AuthUserRole> userRoleList=userIds.stream().map(val->new AuthUserRole(IDGenerator.genLongId(), roleId,  val)).collect(Collectors.toList());
		
		authUserRoleMapper.batchInsertUserRole(userRoleList);
		this.publisher.publishEvent(new AuthChangeEvent(SecurityUtils.getSubject(),AuthCacheClearType.cachedAuthorizationInfoBySubject));
	}
	  
	@Transactional(rollbackFor=Exception.class)
	@Override
	public  void removeRolesFromUserRole(List<Long> roleIds,Long userId){
		roleIds=roleIds.stream().distinct().collect(Collectors.toList());
		authUserRoleMapper.deleteRolesFromUserRole(roleIds, userId);
		this.publisher.publishEvent(new AuthChangeEvent(SecurityUtils.getSubject(),AuthCacheClearType.cachedAuthorizationInfoBySubject));
	}
	  
	@Transactional(rollbackFor=Exception.class)
	@Override
	public void removeUsersFromUserRole(List<Long> userIds,Long roleId){
		userIds=userIds.stream().distinct().collect(Collectors.toList());
		authUserRoleMapper.deleteUsersFromUserRole(userIds, roleId);
		this.publisher.publishEvent(new AuthChangeEvent(SecurityUtils.getSubject(),AuthCacheClearType.cachedAuthorizationInfoBySubject));
	}
	  
//---------------------------------------------------------------------------------------------------------------------
	@Transactional(rollbackFor=Exception.class,readOnly=true)	
	@Override
	public DataSet loadRoleDataSetForUserAssign(Boolean isInUser ,Map<String, Object> params ) {
		ParamMap pm=ParamMap.filterParam(params);
		if(!pm.getStr("appKey").isPresent()||!pm.getLong("userId").isPresent()){
			return DataSet.emptyDS();
		}
		pm.getStr("name").ifPresent(v->pm.updateParam( "name", "%"+v+"%"));
		pm.getStr("roleCode").ifPresent(v->pm.updateParam( "roleCode", "%"+v+"%"));
		pm.addParam("userId", pm.getLong("userId").get());
		
		if(isInUser){
			return DataSet.newDS(authUserRoleMapper.selectRolesInUserCount(pm), authUserRoleMapper.selectRolesInUser(pm));
		} else{
			return DataSet.newDS(authUserRoleMapper.selectRolesNotInUserCount(pm), authUserRoleMapper.selectRolesNotInUser(pm));
		}
	}
}
